<template>
    <div>
      <span>纵向集群卡片拓扑图</span>
      <div class="topology-svg-container">
        <svg :width="svgWidth" :height="svgHeight">
          <!-- 连线 -->
          <g>
            <line
              v-for="(edge, idx) in data.edges"
              :key="idx"
              :x1="getEdgePoint(edge.source, edge.sDirection).x"
              :y1="getEdgePoint(edge.source, edge.sDirection).y"
              :x2="getEdgePoint(edge.target, edge.tDirection).x"
              :y2="getEdgePoint(edge.target, edge.tDirection).y"
              :stroke="getLineColor(edge.edgesType)"
              stroke-width="3"
              marker-end="url(#arrow)"
            />
          </g>
          <!-- 箭头定义 -->
          <defs>
            <marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto" markerUnits="strokeWidth">
              <path d="M2,2 L8,5 L2,8" fill="#409EFF"/>
            </marker>
          </defs>
          <!-- 节点卡片 -->
          <g>
            <g v-for="node in data.nodes" :key="node.id">
              <rect
                :x="node.x"
                :y="node.y"
                :width="node.width"
                :height="node.height"
                :rx="12"
                :class="node.className"
                :fill="getNodeColor(node.className)"
                stroke="#409EFF"
                stroke-width="2"
              />
              <text
                :x="node.x + node.width / 2"
                :y="node.y + node.height / 2"
                text-anchor="middle"
                alignment-baseline="middle"
                font-size="16"
                fill="#222"
              >{{ node.text }}</text>
            </g>
          </g>
        </svg>
      </div>
    </div>
  </template>
  
  <script setup lang="ts">
  import { reactive } from 'vue'
  
  // 伪造数据
  const data = reactive({
    nodes: [
      { id: "node1", x: 361, y: 20, height: 50, width: 180, text: "浏览器发起'www.qq.com'请求", className: "node success" },
      { id: "node2", x: 391, y: 100, height: 50, width: 120, text: "本地hosts文件解析", className: "node success" },
      { id: "node3", x: 301, y: 200, height: 50, width: 100, text: "客户接入联通网", className: "node" },
      { id: "node4", x: 400, y: 200, height: 50, width: 100, text: "客户接入移动网", className: "node" },
      { id: "node5", x: 499, y: 200, height: 50, width: 100, text: "客户接入电信网", className: "node success" },
      { id: "node6", x: 233, y: 300, height: 50, width: 140, text: "联通DNS服务器", className: "node" },
      { id: "node7", x: 372, y: 300, height: 50, width: 140, text: "移动DNS服务器", className: "node" },
      { id: "node8", x: 511, y: 300, height: 50, width: 140, text: "电信DNS服务器", className: "node success" },
      { id: "node9", x: 233, y: 400, height: 50, width: 370, text: "核心骨干交换网集群", className: "node success" },
      { id: "node19", x: 343, y: 500, height: 50, width: 150, text: "WEb服务器", className: "node success" }
    ],
    edges: [
      { source: "node1", sDirection: 'bottom', target: "node2", tDirection: 'top', edgesType: "success" },
      { source: "node2", sDirection: 'bottom', target: "node5", tDirection: 'top', edgesType: "success" },
      { source: "node3", sDirection: 'bottom', target: "node6", tDirection: 'top', edgesType: "danger" },
      { source: "node6", sDirection: 'bottom', target: "node9", tDirection: 'left', edgesType: "danger" },
      { source: "node4", sDirection: 'bottom', target: "node7", tDirection: 'top', edgesType: "danger" },
      { source: "node5", sDirection: 'bottom', target: "node8", tDirection: 'top', edgesType: "success" },
      { source: "node7", sDirection: 'bottom', target: "node9", tDirection: 'top', edgesType: "danger" },
      { source: "node8", sDirection: 'bottom', target: "node9", tDirection: 'right', edgesType: "danger" },
      { source: "node9", sDirection: 'bottom', target: "node19", tDirection: 'top', edgesType: "success" }
    ]
  })
  
  const svgWidth = 900
  const svgHeight = 600
  
  // 获取节点的某个方向的锚点坐标
  function getEdgePoint(nodeId: string, direction: string) {
    const node = data.nodes.find(n => n.id === nodeId)
    if (!node) return { x: 0, y: 0 }
    switch (direction) {
      case 'top':
        return { x: node.x + node.width / 2, y: node.y }
      case 'bottom':
        return { x: node.x + node.width / 2, y: node.y + node.height }
      case 'left':
        return { x: node.x, y: node.y + node.height / 2 }
      case 'right':
        return { x: node.x + node.width, y: node.y + node.height / 2 }
      default:
        return { x: node.x + node.width / 2, y: node.y + node.height / 2 }
    }
  }
  
  // 线条颜色
  function getLineColor(type: string) {
    switch (type) {
      case 'connected': return '#46C37B'
      case 'disconnected': return '#c94d3c'
      default: return '#aaa'
    }
  }
  
  // 节点颜色
  function getNodeColor(className: string) {
    if (className.includes('success')) return '#e8f8f2'
    return '#fff'
  }
  </script>
  
  <style scoped>
  .topology-svg-container {
    width: 900px;
    height: 600px;
    background: #f8f9fa;
    border-radius: 12px;
    margin: 24px auto;
    box-shadow: 0 2px 12px 0 rgba(59, 130, 246, 0.08), 0 1.5px 6px 0 rgba(0, 0, 0, 0.06);
    overflow: auto;
  }
  .node {
    /* 只是给rect用的class，实际颜色用getNodeColor控制 */
  }
  </style>